<template>
  <div class="com-db-hub">
    <div class="db-hub-container">
      <DbNav ref="DbNav"></DbNav>
      <div class="db-hub-main">
        <div class="glb no-select">
          <div class="auto-flex cy">
            <strong class="p f16" @contextmenu="$root.copy(dbTable)">
              <i class="glyphicon glyphicon-flag"></i>
              <span>{{ dbTable.replaceAll('`', '') }}</span>
            </strong>
          </div>
          <div>
            <button class="btn btn-success btn-sm"
              v-if="$root.is.local"
              @click="$root.openFile($options.__file)"
            >打开组件</button>
          </div>
          <div>
            <div class="btn-group">
              <button type="button"
                v-for="(v, idx) in tab.list"
                :key="idx"
                :class="['btn btn-sm btn-' + (v.com === curTab ? 'primary' : 'default')]"
                @click="$root.setRouter({
                  com: r.com,
                  curDB: r.curDB,
                  curTable: r.curTable,
                  curTab: v.com,
                })"
              >{{ v.name }}</button>
            </div>
          </div>
        </div>
        <div class="auto-flex">
          <Component :is="curTab" :ref="curTab"></Component>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import DbNav from './db-nav.vue'
import MainTableData from './main-table-data.vue'
import MainStructure from './main-structure.vue'
import DialogOperRow from './dialog-oper-row.vue'

export default {
  components: {
    DbNav,
    MainTableData,
    MainStructure,
    DialogOperRow,
  },
  name: 'com-db-hub',
  data() {
    const tab = {
      list: [
        {name: '浏览数据', com: 'main-table-data'},
        {name: '库表结构', com: 'main-structure'},
        {name: '存储过程', com: 'main-proc'},
        {name: '存储函数', com: 'main-fx'},
      ]
    }

    return {
      tab,
      def: {
        time: 0,
        serverLang: '',
        dbInfo: {},
        server: {},
        gs: [],
        vars: [],
        engines: {},
        charset: [],
        collation: [],
        php_ini: {},
      },
      db: {
        isLoading: true,
        sc: '',
        list: []
      },
      table: {
        isLoading: true,
        sc: '',
        list: []
      },
      field: {
        isLoading: true,
        list: []
      },
      data: {
        isLoading: true,
        list: []
      },
      page: {
        cur: 1,
        size: 100,
        total: 0,
      }
    }
  },
  computed: {
    r() {
      return this.$root.router
    },
    curTab() {
      const curTab = this.r.curTab
      return curTab && this.tab.list.some(v => v.com === curTab) ? curTab : this.tab.list[0].com
    },
    scDB() {
      return this.db.sc
    },
    scTable() {
      return this.table.sc['Create Table'] ? this.table.sc['Create Table'] : this.$root.formatSc(this.table.sc['Create View'])
    },
    curDB() {
      const curDB = this.r.curDB
      return curDB && this.db.list.some(v => v === curDB) ? curDB : this.db.list[0] || ''
    },
    curTable() {
      const curTable = this.r.curTable
      return curTable && this.table.list.some(v => v === curTable) ? curTable : this.table.list[0] || ''
    },
    dbTable() {
      if (!this.curDB) return '';
      return '`' + this.curDB + '`' + (this.curTable ? '.`' + this.curTable + '`' : '')
    },
    fields() {
      return this.field.list.map(v => v.Field)
    },
    fieldKeys() {
      return Object.keys(this.field.list[0] || {})
    },
    keys() {
      const list = this.field.list
      let keys = list.filter(v => v.Key === 'PRI').map(v => v.Field)
      !keys.length && (keys = list.filter(v => v.Key === 'UNI').map(v => v.Field))
      !keys.length && (keys = list.filter(v => v.Key).map(v => v.Field))
      !keys.length && (keys = list.map(v => v.Field))
      return keys
    },
  },
  watch: {
    curDB() {
      this.lsTable()
    },
    curTable(newVal) {
      if (!newVal) return
      this.lsField()
    },
    'page.cur'() {
      this.lsData()
    },
    'page.size'() {
      this.lsData()
    },
  },
  methods: {
    async runSql(sql) {
      console.log('%crunSql', 'font-weight: bold; color: #09f', sql)
    },
    async post(data) {
      return vm.post('api/db-hub.php', {
        dbHost: 'localhost',
        dbUser: 'root',
        dbPwd: 'root',
        // dbHost: 'qdm722898566.my3w.com',
        // dbUser: 'qdm722898566',
        // dbPwd: 'Tianshihua1',
        curDB: this.curDB,
        curTable: this.curTable,
        ...data
      })
    },
    async lsDef() {
      await this.post({
        a: 'ls-def'
      }).then(async (data) => {
        this.def = data
        await this.lsDB()
      }).catch((xhr, data) => {
        console.error(xhr, data)
      })

      this.db.isLoading = false
      this.table.isLoading = false
      this.field.isLoading = false
      this.data.isLoading = false
    },
    async lsDB() {
      this.db.isLoading = true
      this.table.isLoading = true
      this.field.isLoading = true
      this.data.isLoading = true

      this.db.sc = ''
      this.db.list = []
      this.table.sc = ''
      this.table.list = []
      this.field.list = []
      this.data.list = []

      const signLsDB = this.signLsDB = Math.random()
      await sleep(10)
      if (signLsDB !== this.signLsDB) return new Promise(() => void(0))

      await this.post({
        a: 'ls-db'
      }).then(async (data) => {
        if (signLsDB !== this.signLsDB) return new Promise(() => void(0))
        this.db.list = data
        await this.lsTable()
      }).catch((xhr, data) => {
        console.error(xhr, data)
      })

      this.db.isLoading = false
    },
    async lsTable() {
      this.table.isLoading = !!this.curDB
      this.field.isLoading = !!this.curDB
      this.data.isLoading = !!this.curDB

      this.db.sc = ''
      this.table.sc = ''
      this.table.list = []
      this.field.list = []
      this.data.list = []

      if (!this.curDB) return

      const signLsTable = this.signLsTable = Math.random()
      await sleep(10)
      if (signLsTable !== this.signLsTable) return new Promise(() => void(0))

      await this.post({
        a: 'ls-table',
      }).then(async (data) => {
        if (signLsTable !== this.signLsTable) return new Promise(() => void(0))
        this.db.sc = data.scDB
        this.table.list = data.list
        this.$refs.DbNav?.setScrollTop()
        await this.lsField()
      }).catch((xhr, data) => {
        console.error(xhr, data)
      })

      this.table.isLoading = false
    },
    async lsField() {
      this.field.isLoading = !!this.curTable
      this.data.isLoading = !!this.curTable

      this.table.sc = ''
      this.field.list = []
      this.data.list = []
      this.page.cur = 1

      if (!this.curTable) return

      const signLsField = this.signLsField = Math.random()
      await sleep(10)
      if (signLsField !== this.signLsField) return new Promise(() => void(0))

      await this.post({
        a: 'ls-field',
      }).then(async (data) => {
        if (signLsField !== this.signLsField) return new Promise(() => void(0))
        this.table.sc = data.scTable
        this.field.list = data.list
        await this.lsData()
      }).catch((xhr, data) => {
        console.error(xhr, data)
      })

      this.field.isLoading = false
    },
    async lsData() {
      this.data.isLoading = !!this.curTable
      this.data.list = []

      if (!this.fields.length) return
      
      const page = this.page
      const signLsData = this.signLsData = Math.random()
      await sleep(10)
      if (signLsData !== this.signLsData) return new Promise(() => void(0))

      await this.post({
        a: 'ls-data',
        pageCur: this.page.cur - 1,
        pageSize: page.size,
      }).then(async (data) => {
        if (signLsData !== this.signLsData) return new Promise(() => void(0))
        page.total = data.total
        this.data.list = data.list
      }).catch((xhr, data) => {
        console.error(xhr, data)
      })

      this.data.isLoading = false
    },
  },
  async mounted() {
    const vm = this.$root
    vm.dbHub = this
    await this.lsDef()
  }
}
</script>

<style lang="less" scoped>
.com-db-hub {
  height: 100%;
  .db-hub-container {
    display: flex; height: 100%;
    .db-hub-main {
      flex: 1; overflow: hidden;
      display: flex; flex-direction: column;
    }
  }
}
</style>